﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;

namespace newcj_routerperformancemonitor.Core
{
    internal class Ping
    {
        private Process _ping;

        private volatile bool _exitFlag;
        private Thread _pingThread;

        public event EventHandler<PingEventArgs> CallBack;

        public string Ip { get; set; }

        public void Start()
        {
            StopThread();
            StartThread();
        }

        private void StartPing()
        {
            if (_ping != null)
            {
                _ping.Dispose();
                _ping = null;
            }
            _exitFlag = false;

            _ping = new Process();
            _ping.StartInfo.FileName = "ping.exe";
            _ping.StartInfo.UseShellExecute = false;
            _ping.StartInfo.RedirectStandardInput = true;
            _ping.StartInfo.RedirectStandardOutput = true;
            _ping.StartInfo.RedirectStandardError = true;
            _ping.StartInfo.CreateNoWindow = true;
            _ping.StartInfo.Arguments = string.Format("{0} -t", Ip);
            _ping.Start();

            while (true)
            {
                if (_exitFlag) break;

                var result = _ping.StandardOutput.ReadLine();
                if (string.IsNullOrEmpty(result)) continue;
                if (result.Contains("Ping 192.168.191.1")) continue;

                if (result.Contains("ms"))
                {
                    var index = result.IndexOf("ms");
                    result = result.Substring(0, index);
                    index = result.LastIndexOf("=");
                    result = result.Substring(index + 1);

                    OnPingCallBack(int.Parse(result));
                }
                else
                {
                    OnPingCallBack(-1);
                }
            }
        }

        public void Stop()
        {
            if (_ping != null)
            {
                StopThread();
                _ping.Dispose();
                _ping = null;
            }
        }

        private void StartThread()
        {
            _pingThread = new Thread(StartPing);
            _pingThread.IsBackground = true;
            _pingThread.Start();
        }

        private void StopThread()
        {
            if (_pingThread != null)
            {
                _exitFlag = true;
                _pingThread.Join();
                _pingThread = null;
            }
        }

        private void OnPingCallBack(int timeout)
        {
            var pingCallBack = CallBack;
            if (pingCallBack != null)
            {
                pingCallBack(this, new PingEventArgs(timeout));
            }
        }
    }

    internal class PingEventArgs : EventArgs
    {
        public int Timeout { get; private set; }

        internal PingEventArgs(int timeout)
        {
            Timeout = timeout;
        }
    }
}
